float CurrentTime;
float4x4 View;
float4x4 Proj;

// x: min start
// y: max start
// z: min end
// w: max end
float4 SizeData;

float3 MinTeint;
float3 MaxTeint;

float2 MinMaxRotation;
// x : maximum age of the particle
// y : duration randomness amount (parametrized by vertex data)
float2 Duration;

float EndVelocityRatio;

float3 EnvironmentForces;

float AlphaRatio;



// Vertex shader input structure describes the start position and
// velocity of the particle, and the time at which it was created,
// along with some random values that affect its size and rotation.
struct VertexShaderInput
{
     float2 Corner : POSITION0;

        // Stores the starting position of the particle.
     float3 InitialPosition : POSITION1;

        // Stores the starting velocity of the particle.
     float3 InitialVelocity : NORMAL0;

        // Four random values, used to make each particle look slightly different.
		// x: size random value
		// y: aging random value
		// z: rotation random value
		// w: teint random value
     float4 Random:TEXCOORD0;

        // The time (in seconds) at which this particle was created.
     float StartTime :TEXCOORD1;
};


// Vertex shader output structure specifies the position and color of the particle.
struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 TextureCoordinate : COLOR1;
	float4 Teint : COLOR0;
};



float3 ComputeParticleCenterPosition(VertexShaderInput i, float age, float normalizedAge)
{
	float initialVelocityAmount = length(i.InitialVelocity);
	float endVelocityAmount = initialVelocityAmount * EndVelocityRatio;
	float velocityIntegral = initialVelocityAmount * normalizedAge +
                             (endVelocityAmount - initialVelocityAmount) * normalizedAge *
                                                             normalizedAge / 2;

	// constant velocity
	float3 pos = i.InitialPosition + (velocityIntegral * normalize(i.InitialVelocity) * Duration.x);

	
    pos += EnvironmentForces * age * normalizedAge;

	return pos;
};

float ComputeSize(VertexShaderInput i, float normalizedAge)
{
	float start = lerp(SizeData.x, SizeData.y, i.Random.x);
	float end = lerp(SizeData.z, SizeData.w, i.Random.x);
	return 0.5 * lerp(start, end, normalizedAge);
};

float2x2 ComputeParticleRotation(VertexShaderInput i, float age)
{
	float speed = lerp(MinMaxRotation.x, MinMaxRotation.y, i.Random.z);
	float amount = speed * age;
	
    // Compute a 2x2 rotation matrix.
    float c = cos(amount);
    float s = sin(amount);
    
    return float2x2(c, -s, s, c);
};

// Custom vertex shader animates particles entirely on the GPU.
VertexShaderOutput main(VertexShaderInput i)
{
    VertexShaderOutput o;

	float age = CurrentTime - i.StartTime;
	float duration = Duration.x * (1+ Duration.y * (i.Random.y - 0.5));
	float normalizedAge = saturate(age / Duration);
	float2x2 rotation = ComputeParticleRotation(i, age);
	float4 centerPos = float4(ComputeParticleCenterPosition(i, age, normalizedAge),1);
	centerPos = mul(centerPos,View);
	o.Position = centerPos + float4(mul(ComputeSize(i, normalizedAge) * i.Corner, rotation),0,0);
	o.Position = mul(o.Position, Proj);
	o.TextureCoordinate = (i.Corner + 1) * 0.5;
	
	float alpha =  normalizedAge * (1-normalizedAge) * (1-normalizedAge) * 6.7;
	o.Teint = float4(lerp(MinTeint, MaxTeint, i.Random.w), alpha * AlphaRatio);
	return o;
}




